// client.js   ---start
(function(window, document, navigator) {
  //单一窗口:
  var installlerUrl; ////="http://patchdownload.chinaport.gov.cn/EportClient/EportClientSetup_V1.5.3.exe";
  //安装包动获取地址
  var swVersionScript = 'https://app.singlewindow.cn/sat/swVersion.js';
  //客户端控件安装包下载地址;
  if (!window.SwVersion) {
    var onloadFunc = function() {
      var jsDom = document.createElement('script');
      jsDom.setAttribute('type', 'text/javascript');
      jsDom.setAttribute('src', swVersionScript + '?d=' + new Date().getTime());
      document.body.appendChild(jsDom);
      installlerUrl = window.SwVersion && window.SwVersion.getIkeyDownloadUrl();
      if (!installlerUrl) {
        setTimeout(function() {
          installlerUrl = window.SwVersion && window.SwVersion.getIkeyDownloadUrl();
          if (window.console && window.console.log) {
            window.console.log(
              '%c installlerUrl地址为:' + installlerUrl,
              'color:#1941EC;font-size:12px'
            );
          }
        }, 3000); //等待3秒渲染
      }
    };
    //页面完全加载之后运行
    if (window.addEventListener) {
      ///新的浏览器标准.
      window.addEventListener('load', onloadFunc, false);
    } else if (window.attachEvent) {
      ///兼容IE8以下的浏览器.
      window.attachEvent('onload', onloadFunc);
    } else {
      window.onload = onloadFunc;
    }
  }
  //再次试图加载installlerUrl,保险机制
  if (!installlerUrl) {
    setTimeout(function() {
      installlerUrl = window.SwVersion && window.SwVersion.getIkeyDownloadUrl();
      if (window.console && window.console.log) {
        window.console.log(
          '%c installlerUrl地址为:' + installlerUrl,
          'color:#1941EC;font-size:12px'
        );
      }
    }, 3000); //
  }
  //默认连接类型等待3秒渲染
  var DefaultType = 'iKey';
  // //互联网+
  // //客户端控件安装包下载地址;
  // var installlerUrl;
  // //默认连接类型
  // var DefaultType = "iKeyEportCus";

  //对象转Json
  var toJson = function(obj) {
    if (window.JSON) {
      return JSON.stringify(obj);
    } else {
      alert('JSON转换错误!');
      return null;
    }
  };

  //返回值Json转对象
  var jsonToObj = function(text) {
    if (window.JSON) {
      return JSON.parse(text);
    } else {
      return eval('(' + text + ')');
    }
  };

  var getGuid = function() {
    var s4 = function() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    };
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
  };

  //计算数据分块
  var splitStrData = function(dataStr) {
    if (typeof dataStr !== 'string') {
      throw new Error('数据类型错误');
    }
    var MaxLength = 120 * 1024;
    var byteCount = 0,
      p = 0;
    var rst = [];
    for (var i = 0; i < dataStr.length; i++) {
      var _escape = escape(dataStr.charAt(i));
      byteCount =
        byteCount +
        (_escape.length >= 4 && _escape.charAt(0) === '%' && _escape.charAt(1) === 'u' /*汉字*/
          ? 3
          : 1);
      if (byteCount > MaxLength - 3) {
        rst.push(dataStr.substring(p, i + 1));
        p = i + 1;
        byteCount = 0;
      }
    }
    if (p !== dataStr.length) {
      rst.push(dataStr.substring(p));
    }
    return rst;
  };

  //"BLOCKTXT"+总校验码(4字节)+块校验码(4字节)+数据总大小(16字节)+当前块大小(8字节)+是否分块/分为几块(4字节)+数据分块组号(36字节)+数据包号(4字节)+保留位(44字节),总计128字长
  //        8               12              16                 32                40                       44                   80              84            128
  var getDataHeader = function(
    checkCode,
    blockCheckCode,
    size,
    currsize,
    blockCount,
    blockGuid,
    blockNum
  ) {
    var rst = 'BLOCKTXT'; //8
    rst += equilongString(checkCode, 4, '0'); //4
    rst += equilongString(blockCheckCode, 4, '0'); //4
    rst += equilongString(size, 16, '0'); //16
    rst += equilongString(currsize, 8, '0'); //8
    rst += equilongString(blockCount, 4, '0'); //4
    rst += equilongString(blockGuid, 36, '0'); //36
    rst += equilongString(blockNum, 4, '0'); //4
    rst +=
      '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; //128个占位符0
    return rst.substring(0, 128); //截取前128个子
  };

  //获取等长字符串,默认补0
  var equilongString = function(str, length, prefix) {
    if (!str) {
      str = '';
    }
    if (typeof str !== 'string') {
      str = str + '';
    }
    if (!prefix) {
      prefix = '0';
    }
    var diff = length - str.length;
    for (var i = 0; i < diff; i++) {
      str = prefix + str;
    }
    return str;
  };

  //判断IE
  var isIE6789 = function() {
    var version = !!navigator.appVersion ? navigator.appVersion.split(';') : [];
    var trim_Version = version.length > 1 ? version[1].replace(/[ ]/g, '') : '';
    return (
      navigator.appName === 'Microsoft Internet Explorer' &&
      (trim_Version === 'MSIE6.0' ||
        trim_Version === 'MSIE7.0' ||
        trim_Version === 'MSIE8.0' ||
        trim_Version === 'MSIE9.0')
    );
  };

  //IE6789,创建WebSocket对象
  if (!window.WebSocket && isIE6789()) {
    //alert("IE~");
    WebSocket = function(url) {
      this.activeXObject = new ActiveXObject('snsoft.WebSocket');
      var _self = this,
        ax = this.activeXObject;
      setTimeout(function() {
        ax.websocketOpen(_self, url);
      }, 0);
    };
    WebSocket.prototype = {
      _callback: function(call, ev) {
        var f;
        if (typeof (f = this[call]) === 'function') {
          f.call(this, ev);
        }
      },
      getReadyState: function(type) {
        return this.activeXObject.getReadyState(type || DefaultType);
      },
      send: function(data) {
        this.activeXObject.websocketSendText(data);
      },
      close: function() {
        this.activeXObject.websocketClose();
      },
    };
  }

  //连接本地服务
  var ws;
  var conn = function() {
    //readyState->0:尚未建立连接;1:已经建立连接;2:正在关闭;3:已经关闭或不可用
    //=0的时候不要创建新的了,连接慢的情况下,创建新的可能会更慢!
    if (!ws || getWebSocketReadyState(ws) === 2 || getWebSocketReadyState(ws) === 3) {
      try {
        //改为:http协议页面,使用ws://127.0.0.1:61232地址,其他使用wss://wss.singlewindow.cn:61231
        var websocketurl =
          !!window.location && window.location.protocol === 'http:'
            ? 'ws://127.0.0.1:61232'
            : 'wss://wss.singlewindow.cn:61231';
        if (window.console && window.console.log) {
          window.console.log(
            '%c 使用' + websocketurl + '连接控件服务',
            'color:#1941EC;font-size:12px'
          );
        }
        ws = new WebSocket(websocketurl); //'wss://testlocal.sino-clink.com.cn:61231'
        //WebSocket事件
        ws.onmessage = function(e) {
          if (e.data.charAt(0) === '{') {
            var msg = jsonToObj(e.data);
            //if(msg&&msg['_method']=="open"){
            //握手成功,停掉timeTask的Task
            //	clearTimeout(timeTask);
            //}
            if (window.console && window.console.log) {
              var errMsg =
                '调用' +
                msg['_method'] +
                '方法已返回, Result=' +
                (msg['_args'] && msg['_args'].Result);
              var errStyle = 'color:#1941EC;font-size:12px';
              if (!(msg['_args'] && msg['_args'].Result)) {
                errMsg += ', CallbackInfos=' + e.data;
                errStyle = 'color:#D94E34;font-size:14px';
              }
              window.console.log('%c ' + errMsg, errStyle);
            }
            if (callbacks[msg['_method']]) {
              callbacks[msg['_method']](msg['_args'], e.data);
            }
          } else {
            alert('数据格式非法:' + e.data);
          }
        };
      } catch (ex) {
        if (console && console.log) {
          console.log(ex);
        }
      }
    }
    return ws;
  };

  ws = conn();

  //setInterval(conn,10000);//每10秒检查一次

  /**
   * 回调函数集合
   * @type {{}}
   */
  var callbacks = {};

  /**
   * 分块数据{guid:{checkcode:"98AC",totalLength:14571,retry:0,block:[data1,data2,data3,...]},...}
   * @type {{}}
   */
  var blockData = {};

  var sendMessage = function(msg, callback) {
    if (getWebSocketReadyState(ws) === 1) {
      ws.send(msg);
    } else {
      //如果状态为0
      var times = 0;
      var waitForWebSocketConn = function() {
        if (times > 9) {
          //throw new Error("连接客户端控件服务失败，请重试。");
          callback({
            Result: false,
            Data: [],
            Error: ['连接客户端控件服务失败,请重试.', 'Err:Base60408'],
          });
          conn(); //重连
        } else {
          if (getWebSocketReadyState(ws) === 0) {
            //试图等待500毫秒
            setTimeout(function() {
              if (getWebSocketReadyState(ws) === 1) {
                ws.send(msg);
              } else {
                times++;
                waitForWebSocketConn();
              }
            }, 500);
          } else if (getWebSocketReadyState(ws) === 2 || getWebSocketReadyState(ws) === 3) {
            //试图重连
            times++;
            conn(); //重连
          }
        }
      };
      waitForWebSocketConn();
    }
  };

  /**
   * 分块的回调函数
   * @param args:{id:1,guid:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",next:1,finish:false}
   * @private
   */
  callbacks._nextBlock = function(args) {
    var guid = args.Data[0]['guid'];
    if (args.Data[0]['finish']) {
      //要从内存中释放掉这个数据
      if (blockData[guid]) {
        delete blockData[guid];
      }
    } else {
      //传输
      conn();
      var next = args.Data[0]['next'];
      var blockObj = blockData[guid];
      if (!args.Result) {
        //失败的
        var retry = blockObj['retry'] || 0;
        retry = retry + 1;
        blockObj['retry'] = retry;
        if (retry > blockObj.block.length * 3) {
          //达到最大重试次数
          alert('数据接收错误!');
        }
      }
      var currData = blockObj.block[next];
      var blockCheckCode = DIGEST.CheckCode(currData);
      var pakHeaser = getDataHeader(
        blockObj['checkcode'],
        blockCheckCode,
        blockObj['totalLength'],
        currData.length,
        blockObj.block.length,
        guid,
        next
      );
      var msg = pakHeaser + currData;
      sendMessage(msg);
      //alert(toJson(args));
    }
  };

  /**
   * 一种简化的摘要校验码,相比于CRC,对汉字的编码做的简化的处理,提高了一些效率.
   * @type {Object}
   */
  var DIGEST = {};
  DIGEST._auchCRCHi = [
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x01,
    0xc0,
    0x80,
    0x41,
    0x00,
    0xc1,
    0x81,
    0x40,
  ];
  DIGEST._auchCRCLo = [
    0x00,
    0xc0,
    0xc1,
    0x01,
    0xc3,
    0x03,
    0x02,
    0xc2,
    0xc6,
    0x06,
    0x07,
    0xc7,
    0x05,
    0xc5,
    0xc4,
    0x04,
    0xcc,
    0x0c,
    0x0d,
    0xcd,
    0x0f,
    0xcf,
    0xce,
    0x0e,
    0x0a,
    0xca,
    0xcb,
    0x0b,
    0xc9,
    0x09,
    0x08,
    0xc8,
    0xd8,
    0x18,
    0x19,
    0xd9,
    0x1b,
    0xdb,
    0xda,
    0x1a,
    0x1e,
    0xde,
    0xdf,
    0x1f,
    0xdd,
    0x1d,
    0x1c,
    0xdc,
    0x14,
    0xd4,
    0xd5,
    0x15,
    0xd7,
    0x17,
    0x16,
    0xd6,
    0xd2,
    0x12,
    0x13,
    0xd3,
    0x11,
    0xd1,
    0xd0,
    0x10,
    0xf0,
    0x30,
    0x31,
    0xf1,
    0x33,
    0xf3,
    0xf2,
    0x32,
    0x36,
    0xf6,
    0xf7,
    0x37,
    0xf5,
    0x35,
    0x34,
    0xf4,
    0x3c,
    0xfc,
    0xfd,
    0x3d,
    0xff,
    0x3f,
    0x3e,
    0xfe,
    0xfa,
    0x3a,
    0x3b,
    0xfb,
    0x39,
    0xf9,
    0xf8,
    0x38,
    0x28,
    0xe8,
    0xe9,
    0x29,
    0xeb,
    0x2b,
    0x2a,
    0xea,
    0xee,
    0x2e,
    0x2f,
    0xef,
    0x2d,
    0xed,
    0xec,
    0x2c,
    0xe4,
    0x24,
    0x25,
    0xe5,
    0x27,
    0xe7,
    0xe6,
    0x26,
    0x22,
    0xe2,
    0xe3,
    0x23,
    0xe1,
    0x21,
    0x20,
    0xe0,
    0xa0,
    0x60,
    0x61,
    0xa1,
    0x63,
    0xa3,
    0xa2,
    0x62,
    0x66,
    0xa6,
    0xa7,
    0x67,
    0xa5,
    0x65,
    0x64,
    0xa4,
    0x6c,
    0xac,
    0xad,
    0x6d,
    0xaf,
    0x6f,
    0x6e,
    0xae,
    0xaa,
    0x6a,
    0x6b,
    0xab,
    0x69,
    0xa9,
    0xa8,
    0x68,
    0x78,
    0xb8,
    0xb9,
    0x79,
    0xbb,
    0x7b,
    0x7a,
    0xba,
    0xbe,
    0x7e,
    0x7f,
    0xbf,
    0x7d,
    0xbd,
    0xbc,
    0x7c,
    0xb4,
    0x74,
    0x75,
    0xb5,
    0x77,
    0xb7,
    0xb6,
    0x76,
    0x72,
    0xb2,
    0xb3,
    0x73,
    0xb1,
    0x71,
    0x70,
    0xb0,
    0x50,
    0x90,
    0x91,
    0x51,
    0x93,
    0x53,
    0x52,
    0x92,
    0x96,
    0x56,
    0x57,
    0x97,
    0x55,
    0x95,
    0x94,
    0x54,
    0x9c,
    0x5c,
    0x5d,
    0x9d,
    0x5f,
    0x9f,
    0x9e,
    0x5e,
    0x5a,
    0x9a,
    0x9b,
    0x5b,
    0x99,
    0x59,
    0x58,
    0x98,
    0x88,
    0x48,
    0x49,
    0x89,
    0x4b,
    0x8b,
    0x8a,
    0x4a,
    0x4e,
    0x8e,
    0x8f,
    0x4f,
    0x8d,
    0x4d,
    0x4c,
    0x8c,
    0x44,
    0x84,
    0x85,
    0x45,
    0x87,
    0x47,
    0x46,
    0x86,
    0x82,
    0x42,
    0x43,
    0x83,
    0x41,
    0x81,
    0x80,
    0x40,
  ];

  DIGEST.CheckCode = function(buffer) {
    var hi = 0xff;
    var lo = 0xff;
    for (var i = 0; i < buffer.length; i++) {
      var idx = 0xff & (hi ^ buffer.charCodeAt(i));
      hi = lo ^ DIGEST._auchCRCHi[idx];
      lo = DIGEST._auchCRCLo[idx];
    }
    return DIGEST.padLeft(((hi << 8) | lo).toString(16).toUpperCase(), 4, '0');
  };
  DIGEST.padLeft = function(s, w, pc) {
    if (pc === undefined) {
      pc = '0';
    }
    for (var i = 0, c = w - s.length; i < c; i++) {
      s = pc + s;
    }
    return s;
  };

  var id = 0;

  //调用本地服务方法的抽象(数据不分包)
  var baseInvoke = function(method, args, callback) {
    if (typeof args === 'function') {
      callback = args;
      args = {};
    }
    conn();
    if (window.console && window.console.log) {
      window.console.log('%c 调用方法' + method, 'color:#95F065;font-size:12px');
    }
    callbacks[method] = callback;
    var _data = { _method: method };
    _data['_id'] = id++;
    args = args || {};
    _data['args'] = args;
    var s = toJson(_data);
    if (getWebSocketReadyState(ws) === 0) {
      setTimeout(function() {
        //建立连接需要时间~ 首次延迟半秒~
        sendMessage(s, callback);
      }, 500);
    } else {
      sendMessage(s, callback);
    }
  };

  var baseInvokeByFrames = function(method, args, callback) {
    if (typeof args === 'function') {
      callback = args;
      args = {};
    }
    conn();
    if (window.console && window.console.log) {
      window.console.log('%c 调用方法' + method, 'color:#95F065;font-size:12px');
    }
    callbacks[method] = callback;
    var _data = { _method: method };
    _data['_id'] = id++;
    args = args || {};
    _data['args'] = args;
    var s = toJson(_data);
    if (getWebSocketReadyState(ws) === 0 || getWebSocketReadyState(ws) === 3) {
      setTimeout(function() {
        //建立连接需要时间~ 首次延迟半秒~
        sendFrames(s, callback);
      }, 500);
    } else {
      sendFrames(s, callback);
    }
  };

  /**
   * 分帧传输数据
   * @param s 数据
   * @param callback 回调函数
   */
  var sendFrames = function(s, callback) {
    //校验码
    var checkCode = DIGEST.CheckCode(s); //打校验码
    //分包的组
    var guid = getGuid();
    while (blockData[guid]) {
      //存在则重新生成一个!
      guid = getGuid();
    }
    //数据分块
    var splitData = splitStrData(s); //数据切块
    //记录以备重发
    blockData[guid] = { checkcode: checkCode, totalLength: s.length, retry: 0, block: splitData };
    //传第一个包
    //报头(纯文本类型)含义
    //"BLOCKTXT"+总校验码(4字节)+块校验码(4字节)+数据总大小(16字节)+当前块大小(8字节)+是否分块/分为几块(4字节)+数据分块组号(36字节)+数据包号(4字节)+保留位(44字节),总计128字长
    //        8               12              16                 32                40                       44                   80              84            128
    var blockCheckCode = DIGEST.CheckCode(splitData[0]);
    var pakHeaser = getDataHeader(
      checkCode,
      blockCheckCode,
      s.length,
      splitData[0].length,
      splitData.length,
      guid,
      0
    );
    var msg = pakHeaser + splitData[0];
    sendMessage(msg, callback);
  };

  /**
   * readyState->0:尚未建立连接;1:已经建立连接;2:正在关闭;3:已经关闭或不可用
   * @param thisWs
   * @returns {*}
   */
  var getWebSocketReadyState = function(thisWs) {
    var currWs = thisWs || conn();
    if (!currWs) {
      return 0;
    }
    if (currWs.readyState !== undefined) {
      return currWs.readyState;
    }
    if (currWs.getReadyState) {
      //IE8,IE9
      return currWs.getReadyState();
    }
    /*
       if(currWs.activeXObject){//IE8,IE9
       return currWs.activeXObject.readyState;
       }
       */
    return 0;
  };

  window.EportClient = {
    isInstalled: function(type, callback, currInstalllerUrl) {
      //这个方法最慢需要3秒钟返回信息.
      if (typeof type === 'function') {
        if (callback) {
          currInstalllerUrl = callback;
        }
        callback = type;
        type = DefaultType;
      }
      ws = conn();
      var bInstalled = getWebSocketReadyState(ws) === 1;
      var retryConut = 0;

      function retry() {
        retryConut++;
        ws = conn();
        bInstalled = getWebSocketReadyState(ws) === 1;
        if (!bInstalled) {
          if (retryConut < 3) {
            setTimeout(retry, 1500);
          } else if (retryConut === 3) {
            window.location.href = 'singlewindow://Restart';
            setTimeout(retry, 2500);
          } else {
            //未安装
            var errMsg =
              '检测到您未安装' + type + '客户端! ' + type + '下载地址为:' + currInstalllerUrl ||
              installlerUrl ||
              window.installlerUrl;
            if (callback) {
              callback({ Result: false, Data: [], Error: [errMsg] });
            } else {
              if (window.console) {
                window.console.log(errMsg);
              }
              //alert(errMsg);
            }
          }
        } else {
          //已经安装了
          var okMsg = '已经安装了' + type + '客户端.';
          if (callback) {
            callback({ Result: true, Data: [okMsg], Error: [] });
          } else {
            if (window.console) {
              window.console.log(okMsg);
            }
            //alert(okMsg);
          }
        }
      }

      retry();
      //iKeyInstalllerUrl
    },
    /**
     *
     * @param func 被执行函数
     * @param arg1
     * @param arg2
     * @param argX
     */
    isInstalledTest: function(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) {
      //这里argX只多不少即可
      if (!func) {
        throw new Error(
          '未知的JS的function,请检查调用isInstalledTest传入的第一个参数是否存在该函数.'
        );
      }
      EportClient.isInstalled(
        DefaultType,
        function(msg) {
          if (msg.Result) {
            if (func && typeof func === 'function') {
              func.call(null, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
            } else {
              alert(msg.Data[0]);
            }
          } else {
            alertErrMsg(msg);
          }
        },
        installlerUrl || window.installlerUrl
      );
    },
    /*----------------------------------内嵌方法--------------------------------------------------------------------*/
    /**
     * 试图更新控件
     * @param callback
     */
    update: function(callback) {
      conn();
      var method = 'update';
      callbacks[method] = callback;
      var _data = { _method: method };
      _data['_id'] = id++;
      _data['args'] = {};
      var s = toJson(_data);
      sendMessage(s);
    },
    /**
     * 全量更新
     * @param callback
     */
    fullupdate: function(callback) {
      baseInvoke('fullupdate', {}, callback);
    },
    /**
     * 获取控件文件的路径
     * @param file
     * @param callback
     */
    getfilepath: function(file, callback) {
      baseInvoke('getfilepath', { file: file }, callback);
    },
    /**
     * 获取安装包版本号
     * @param callback
     */
    getInstallerVersion: function(callback) {
      baseInvoke('ver', callback);
    },
    /**
     * 获取插件模块版本号
     * @param module 模块名称
     * @param callback
     */
    getModuleVersion: function(module, callback) {
      baseInvoke(module + '_GetVersions', callback);
    },

    /*----------------------------------基础功能--------------------------------------------------------------------*/
    /**
     * 选择文件(打开或读取用)
     * @param filter 文件类型描述
     * @param fileSize 文件大小过滤(限制条件)
     * @param multiSelect 是否多选,Y多选,默认Y
     * @param callback
     */
    choosefile: function(filter, fileSize, multiSelect, callback) {
      if (!callback && !fileSize && !multiSelect && typeof filter === 'function') {
        callback = filter;
        filter = null;
        baseInvoke('base_choosefile', callback);
      } else if (!callback && !multiSelect && typeof fileSize === 'function') {
        callback = fileSize;
        fileSize = null;
        baseInvoke(
          'base_choosefile',
          {
            filter: filter,
          },
          callback
        );
      } else if (!callback && typeof multiSelect === 'function') {
        callback = multiSelect;
        multiSelect = null;
        baseInvoke(
          'base_choosefile',
          {
            filter: filter,
            fileSize: fileSize,
          },
          callback
        );
      } else {
        baseInvoke(
          'base_choosefile',
          {
            filter: filter,
            fileSize: fileSize,
            multiSelect: multiSelect,
          },
          callback
        );
      }
    },
    /**
     * 选择目录,用于保存或者读取文件.
     * @param callback
     */
    chooseDir: function(callback) {
      baseInvoke('base_chooseDir', {}, callback);
    },
    /**
     * 指定文件(保存或写入文件使用)
     * @param filter 文件类型描述
     * @param callback
     */
    savefile: function(filter, callback) {
      if (!callback && typeof filter === 'function') {
        callback = filter;
        filter = null;
        baseInvoke('base_savefile', callback);
      } else {
        baseInvoke('base_savefile', { filter: filter }, callback);
      }
    },
    /**
     * 直接打开ClickOnce地址
     * @param url 地址
     * @param HideIE 是否隐藏IE界面
     * @param callback
     */
    startClickOnceAppWithUser: function(url, HideIE, callback) {
      if (callback && typeof callback === 'function') {
        baseInvoke('base_StartClickOnceAppWithUserinfo', { qpurl: url, HideIE: HideIE }, callback);
      } else if (!callback && typeof HideIE === 'function') {
        callback = HideIE;
        HideIE = null;
        baseInvoke('base_StartClickOnceAppWithUserinfo', { qpurl: url }, callback);
      } else {
        throw new Error('startClickOnceAppWithUser的调用参数非法!');
      }
    },
    /**
     * 打开带有ticket的ClickOnce地址,地址需要包含ticket参数
     * @param url 带有ticket参数的地址
     * @param HideIE 是否隐藏IE界面
     * @param callback
     */
    startClickOnceAppWithTicket: function(url, HideIE, callback) {
      if (callback && typeof callback === 'function') {
      } else if (!callback && typeof HideIE === 'function') {
        callback = HideIE;
        HideIE = null;
      } else {
        throw new Error('startClickOnceAppWithTicket的调用参数非法!');
      }
      if (!url || url === '') {
        callback({
          Result: false,
          Data: [],
          Error: ['args中必须要包含必要的非空的qpurl参数!', 'Err:Base50000'],
        });
        return;
      } else if (url.indexOf('ticket=') < 0 && url.indexOf('ticket =') < 0) {
        callback({
          Result: false,
          Data: [],
          Error: ['args中的url必须要包含ticket!', 'Err:Base50000'],
        });
        return;
      }
      baseInvoke(
        'base_StartClickOnceApp',
        {
          qpurl: url,
          HideIE: HideIE,
          casurl: '-1',
          passwd: '-1',
        },
        callback
      );
    },

    /**
     * 获取打印机列表
     * @param callback
     */
    getLocalPrinters: function(callback) {
      baseInvoke('base_GetLocalPrinters', {}, callback);
    },
    /**
     * 将指定名称的打印机设为系统默认
     * @param printerName 打印机名称
     * @param callback
     */
    setDefaultPrinter: function(printerName, callback) {
      baseInvoke('base_SetDefaultPrinter', { printerName: printerName }, callback);
    },
    /**
     * 打印PDF内容
     * @param fileContent 文件内容,Base64格式
     * @param printerName 打印机名称
     * @param ranges 页码选择(过滤)
     * @param marginLeft 上边距xxx像素,支持负数
     * @param marginTop 左边距xxx像素,支持负数
     * @param milliseconds 超时时间(毫秒) 默认25000
     * @param callback
     */
    printPdf: function(
      fileContent,
      printerName,
      ranges,
      marginLeft,
      marginTop,
      milliseconds,
      callback
    ) {
      if (callback && typeof callback === 'function') {
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: marginTop,
            milliseconds: milliseconds,
          },
          callback
        );
      } else if (!callback && typeof milliseconds === 'function') {
        callback = milliseconds;
        milliseconds = null;
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: marginTop,
          },
          callback
        );
      } else if (!callback && typeof marginTop === 'function') {
        callback = marginTop;
        marginTop = null;
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof marginLeft === 'function') {
        callback = marginLeft;
        marginTop = null;
        marginLeft = null;
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            printerName: printerName,
            ranges: ranges,
            marginLeft: 0,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof ranges === 'function') {
        callback = ranges;
        marginTop = null;
        marginLeft = null;
        ranges = null;
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            printerName: printerName,
            marginLeft: 0,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof printerName === 'function') {
        callback = printerName;
        marginTop = null;
        marginLeft = null;
        ranges = null;
        printerName = null;
        baseInvokeByFrames(
          'base_PrintPdf',
          {
            fileContent: fileContent,
            marginLeft: 0,
            marginTop: 0,
          },
          callback
        );
      } else {
        throw new Error('printPdf的调用参数非法!');
        //alert("printPdf的调用参数非法");
      }
    },
    /**
     * 打印PDF本地文件
     * @param filePath 文件绝对路径
     * @param printerName 打印机名称
     * @param ranges 打印的页面(过滤)
     * @param marginLeft 上边距xxx像素,支持负数
     * @param marginTop 左边距xxx像素,支持负数
     * @param milliseconds 超时时间(毫秒) 默认25000
     * @param callback
     */
    printPdfFile: function(
      filePath,
      printerName,
      ranges,
      marginLeft,
      marginTop,
      milliseconds,
      callback
    ) {
      if (callback && typeof callback === 'function') {
        baseInvoke(
          'base_PrintPdf',
          {
            filePath: filePath,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: marginTop,
            milliseconds: milliseconds,
          },
          callback
        );
      } else if (!callback && typeof milliseconds === 'function') {
        callback = milliseconds;
        milliseconds = null;
        baseInvoke(
          'base_PrintPdf',
          {
            filePath: filePath,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: marginTop,
          },
          callback
        );
      } else if (!callback && typeof marginTop === 'function') {
        callback = marginTop;
        marginTop = null;
        baseInvoke(
          'base_PrintPdf',
          {
            filePath: filePath,
            printerName: printerName,
            ranges: ranges,
            marginLeft: marginLeft,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof marginLeft === 'function') {
        callback = marginLeft;
        marginTop = null;
        marginLeft = null;
        baseInvoke(
          'base_PrintPdf',
          {
            filePath: filePath,
            printerName: printerName,
            ranges: ranges,
            marginLeft: 0,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof ranges === 'function') {
        callback = ranges;
        marginTop = null;
        marginLeft = null;
        ranges = null;
        baseInvoke(
          'base_PrintPdf',
          {
            filePath: filePath,
            printerName: printerName,
            marginLeft: 0,
            marginTop: 0,
          },
          callback
        );
      } else if (!callback && typeof printerName === 'function') {
        callback = printerName;
        marginTop = null;
        marginLeft = null;
        ranges = null;
        printerName = null;
        baseInvoke('base_PrintPdf', { filePath: filePath, marginLeft: 0, marginTop: 0 }, callback);
      } else {
        throw new Error('printLocalPdf的调用参数非法!');
        //alert("printLocalPdf的调用参数非法");
      }
    },
    /**
     * 下载文件
     * @param url 文件下载地址
     * @param localpath 保存在本地的地址
     * @param method http的Method,默认为get
     * @param cookies cookies
     * @param returnData 是否直接返回数据
     * @param callback
     */
    fileDownload: function(url, localpath, method, cookies, returnData, callback) {
      baseInvoke(
        'base_FileDownload',
        {
          url: url,
          localpath: localpath,
          method: method,
          cookies: cookies,
          returnData: returnData,
        },
        callback
      );
    },
    /**
     * 获取文件的大小
     * @param path 本地路径
     * @param callback 回调函数
     */
    fileSize: function(path, callback) {
      baseInvoke('base_FileSize', { path: path }, callback);
    },
    /**
     * 文件批量上传
     * @param args 参见文档
     * @param callback
     */
    fileBatchUpload: function(args, callback) {
      baseInvoke('upload_FileBatchUpload', args, callback);
    },
    /**
     * 删除控件的临时文件
     * @param args 参见文档
     * @param callback
     */
    deleteTempFile: function(args, callback) {
      baseInvoke('base_DeleteTempFiles', args, callback);
    },

    /*----------------------------------海关安全功能-----------------------------------------------------------------*/

    /**
     * 设置加密设备的优先级
     * @param szInitEnvPriority
     * @param callback
     */
    cusSpcSetInitEnvPriority: function(szInitEnvPriority, callback) {
      baseInvoke(
        'cus-sec_SpcSetInitEnvPriority',
        { szInitEnvPriority: szInitEnvPriority },
        callback
      );
    },
    /**
     * 打开卡
     * @param callback
     */
    cusSpcInitEnvEx: function(callback) {
      baseInvoke('cus-sec_SpcInitEnvEx', callback);
    },
    /**
     * 关闭卡
     * @param callback
     */
    cusSpcClearEnv: function(callback) {
      baseInvoke('cus-sec_SpcClearEnv', callback);
    },
    /**
     * 获取附加信息
     * @param callback
     */
    cusSpcGetCardAttachInfo: function(callback) {
      baseInvoke('cus-sec_SpcGetCardAttachInfo', callback);
    },
    /**
     * 获取附加信息(PEM格式)
     * @param callback
     */
    cusSpcGetCardAttachInfoAsPEM: function(callback) {
      baseInvoke('cus-sec_SpcGetCardAttachInfoAsPEM', callback);
    },
    /**
     * 获取卡号
     * @param callback
     */
    cusSpcGetCardID: function(callback) {
      baseInvoke('cus-sec_SpcGetCardID', callback);
    },
    /**
     * 获取证书编号
     * @param callback
     */
    cusSpcGetCertNo: function(callback) {
      baseInvoke('cus-sec_SpcGetCertNo', callback);
    },
    /**
     * 申请者名称
     * @param callback
     */
    cusSpcGetUName: function(callback) {
      baseInvoke('cus-sec_SpcGetUName', callback);
    },
    /**
     * 单位ID
     * @param callback
     */
    cusSpcGetEntID: function(callback) {
      baseInvoke('cus-sec_SpcGetEntID', callback);
    },
    /**
     * 单位名
     * @param callback
     */
    cusSpcGetEntName: function(callback) {
      baseInvoke('cus-sec_SpcGetEntName', callback);
    },
    /**
     * 单位类别
     * @param callback
     */
    cusSpcGetEntMode: function(callback) {
      baseInvoke('cus-sec_SpcGetEntMode', callback);
    },
    /**
     * 用户信息
     * @param callback
     */
    cusSpcGetCardUserInfo: function(callback) {
      baseInvoke('cus-sec_SpcGetCardUserInfo', callback);
    },
    /**
     * 取海关签名证书
     * @param callback
     */
    cusSpcGetSignCert: function(callback) {
      baseInvoke('cus-sec_SpcGetSignCert', callback);
    },
    /**
     * 取海关签名证书PEM
     * @param callback
     */
    cusSpcGetSignCertAsPEM: function(callback) {
      baseInvoke('cus-sec_SpcGetSignCertAsPEM', callback);
    },
    /**
     * 取海关加密证书
     * @param callback
     */
    cusSpcGetEnvCert: function(callback) {
      baseInvoke('cus-sec_SpcGetEnvCert', callback);
    },
    /**
     * 取海关加密证书PEM
     * @param callback
     */
    cusSpcGetEnvCertAsPEM: function(callback) {
      baseInvoke('cus-sec_SpcGetEnvCertAsPEM', callback);
    },
    /**
     * 查看海关证书有效期
     * @param cert 证书内容,可为空
     * @param callback
     */
    cusSpcGetValidTimeFromCert: function(cert, callback) {
      if (typeof cert === 'function') {
        callback = cert;
        cert = null;
      }
      baseInvoke('cus-sec_SpcGetValidTimeFromCert', !!cert ? { cert: cert } : {}, callback);
    },
    /**
     * 验证海关卡密码,仅仅验证密码,不自动开关卡~
     * @param passwd 密码
     * @param callback
     */
    cusSpcVerifyPIN: function(passwd, callback) {
      baseInvoke('cus-sec_SpcVerifyPIN', { passwd: passwd }, callback);
    },
    /**
     * 验证海关卡密码(自动开关卡)
     * @param passwd 密码
     * @param callback
     */
    cusSpcVerifyPINAll: function(passwd, callback) {
      baseInvoke('cus-sec_SpcVerifyPINAll', { passwd: passwd }, callback);
    },
    /**
     * 修改密码
     * @param oldPin 旧密码
     * @param newPin 新密码
     * @param callback
     */
    cusSpcChangePIN: function(oldPin, newPin, callback) {
      baseInvoke('cus-sec_SpcChangePIN', { oldPin: oldPin, newPin: newPin }, callback);
    },
    /**
     * PEM编码
     * @param inData 原始内容
     * @param callback
     */
    cusSpcEncodePEM: function(inData, callback) {
      baseInvoke('cus-sec_SpcEncodePEM', { inData: inData }, callback);
    },
    /**
     * PEM解码
     * @param inData PEM编码的内容(字符串)
     * @param callback
     */
    cusSpcDecodePEM: function(inData, callback) {
      baseInvoke('cus-sec_SpcDecodePEM', { inData: inData }, callback);
    },
    /**
     * PEM解码,返回String类型的原文
     * @param inData PEM编码的内容(字符串)
     * @param callback
     */
    cusSpcDecodePEMAsString: function(inData, callback) {
      baseInvoke('cus-sec_SpcDecodePEMAsString', { inData: inData }, callback);
    },
    /**
     * 签名,返回byte[]
     * @param inData 原文
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcSignData: function(inData, passwd, callback) {
      baseInvoke(
        'cus-sec_SpcSignData',
        !!passwd
          ? {
              inData: inData,
              passwd: passwd,
            }
          : { inData: inData },
        callback
      );
    },
    /**
     * 签名,返回PEM格式
     * @param inData 原文
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcSignDataAsPEM: function(inData, passwd, callback) {
      baseInvoke(
        'cus-sec_SpcSignDataAsPEM',
        !!passwd
          ? {
              inData: inData,
              passwd: passwd,
            }
          : { inData: inData },
        callback
      );
    },

    /**
     * 签名PEM编码格式原文,返回PEM格式
     * @param inData PEM编码格式原文
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcSignPemDataAsPEM: function(inData, passwd, callback) {
      baseInvoke(
        'cus-sec_SpcSignPemDataAsPem',
        !!passwd
          ? {
              inData: inData,
              passwd: passwd,
            }
          : { inData: inData },
        callback
      );
    },

    /**
     * 验证签名
     * @param inData 原文信息
     * @param signData 签名信息
     * @param certDataPEM 签名证书,PEM编码格式 可以为空,则取当前插着的卡中的证书
     * @param callback
     */
    cusSpcVerifySignData: function(inData, signData, certDataPEM, callback) {
      if (!callback && typeof certDataPEM === 'function') {
        callback = certDataPEM;
        certDataPEM = null;
        baseInvoke(
          'cus-sec_SpcVerifySignData',
          {
            inData: inData,
            signData: signData,
          },
          callback
        );
      } else {
        baseInvoke(
          'cus-sec_SpcVerifySignData',
          {
            inData: inData,
            signData: signData,
            certDataPEM: certDataPEM,
          },
          callback
        );
      }
    },
    /**
     * 使用卡计算摘要
     * @param szInfo 原文内容
     * @param callback
     */
    cusSpcSHA1Digest: function(szInfo, callback) {
      baseInvoke('cus-sec_SpcSHA1Digest', { szInfo: szInfo }, callback);
    },
    /**
     * 使用卡计算摘要,返回PEM格式信息
     * @param szInfo 原文内容
     * @param callback
     */
    cusSpcSHA1DigestAsPEM: function(szInfo, callback) {
      baseInvoke('cus-sec_SpcSHA1DigestAsPEM', { szInfo: szInfo }, callback);
    },
    /**
     * 签名,不对原文计算摘要,请您自行计算好摘要传入
     * @param inData 原文的SHA1摘要
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcSignDataNoHash: function(inData, passwd, callback) {
      baseInvoke(
        'cus-sec_SpcSignDataNoHash',
        !!passwd
          ? {
              inData: inData,
              passwd: passwd,
            }
          : { inData: inData },
        callback
      );
    },
    /**
     * 签名,不对原文计算摘要,请您自行计算好摘要传入
     * 返回PEM格式数据
     * @param inData 原文的SHA1摘要
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcSignDataNoHashAsPEM: function(inData, passwd, callback) {
      baseInvoke(
        'cus-sec_SpcSignDataNoHashAsPEM',
        !!passwd
          ? {
              inData: inData,
              passwd: passwd,
            }
          : { inData: inData },
        callback
      );
    },
    /**
     * 验证签名,不对原文计算摘要,请您自行计算好摘要传入
     * @param inData 原文的SHA1摘要
     * @param signData 签名信息
     * @param certDataPEM 签名证书,PEM编码格式 可以为空,则取当前插着的卡中的证书
     * @param callback
     */
    cusSpcVerifySignDataNoHash: function(inData, signData, certDataPEM, callback) {
      if (!callback && typeof certDataPEM === 'function') {
        callback = certDataPEM;
        certDataPEM = null;
        baseInvoke(
          'cus-sec_SpcVerifySignDataNoHash',
          {
            inData: inData,
            signData: signData,
          },
          callback
        );
      } else {
        baseInvoke(
          'cus-sec_SpcVerifySignDataNoHash',
          {
            inData: inData,
            signData: signData,
            certDataPEM: certDataPEM,
          },
          callback
        );
      }
    },
    /**
     * 签名随机数的组和方法
     * @param random 随机数
     * @param passwd 密码
     * @param callback
     */
    cusSpcSignRandom: function(random, passwd, callback) {
      baseInvoke('cus-sec_SpcSignRandom', { random: random, passwd: passwd }, callback);
    },
    /**
     * RSA加密(公钥)
     * @param inData 原文数据
     * @param certData 支持传证书
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcRSAEncrypt: function(inData, certData, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'cus-sec_SpcRSAEncrypt',
          {
            inData: inData,
            certData: certData,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'cus-sec_SpcRSAEncrypt',
          {
            inData: inData,
            certData: certData,
          },
          callback
        );
      } else {
        throw new Error('spcRSAEncrypt的调用参数非法!');
      }
    },
    /**
     * RSA解密
     * @param inData 密文数据
     * @param passwd 卡密码
     * @param callback
     */
    cusSpcRSADecrypt: function(inData, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'cus-sec_SpcRSADecrypt',
          {
            inData: inData,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'cus-sec_SpcRSADecrypt',
          {
            inData: inData,
          },
          callback
        );
      } else {
        throw new Error('spcRSAEncrypt的调用参数非法!');
      }
    },
    /*----------------------------------海关业务功能-----------------------------------------------------------------*/
    /**
     * 扫描仪初始化
     * @param callback
     */
    cusPdfScanInit: function(callback) {
      baseInvoke('pdf-scan_PdfScanScanInitialize', {}, callback);
    },
    /**
     * 使用扫描仪生成PDF文件
     * @param Edoc_code
     * @param Edoc_Name
     * @param fileFullPath 生成文件的目标全路径
     * @param passwd 海关卡密码
     * @param callback
     */
    cusPdfScan: function(Edoc_code, Edoc_Name, fileFullPath, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-scan_PdfScan',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            fileFullPath: fileFullPath,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'pdf-scan_PdfScan',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            fileFullPath: fileFullPath,
          },
          callback
        );
      } else if (!callback && typeof fileFullPath === 'function') {
        //缺少2个参数,我们兼容缺少passwd,fileFullPath的情况
        callback = fileFullPath;
        fileFullPath = null;
        baseInvoke(
          'pdf-scan_PdfScan',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少3个参数,我们兼容缺少passwd,fileFullPath,Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke(
          'pdf-scan_PdfScan',
          {
            Edoc_code: Edoc_code,
          },
          callback
        );
      }
    },
    /**
     * 使用扫描仪生成Base64格式的PDF数据
     * @param Edoc_code
     * @param Edoc_Name
     * @param passwd 海关卡密码
     * @param callback
     */
    cusPdfScanAsPEM: function(Edoc_code, Edoc_Name, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-scan_PdfScanAsPEM',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'pdf-scan_PdfScanAsPEM',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少2个参数,我们兼容缺少passwd和Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke('pdf-scan_PdfScanAsPEM', { Edoc_code: Edoc_code }, callback);
      }
    },
    /**
     * 使用方正组件预览Base64编码的PDF
     * @param fileContent Base64编码的PDF文件
     * @param callback
     */
    cusPdfContentView: function(fileContent, callback) {
      //destDir,fileName,
      baseInvokeByFrames('pdf-sign_PdfView', { fileContent: fileContent }, callback);
    },
    /**
     * 使用方正组件预览本地文件的PDF
     * @param filePath 文件全路径
     * @param cookies Http地址需要的Cookies
     * @param callback
     */
    cusPdfFileView: function(filePath, cookies, callback) {
      //filePath可以是本地的file:,也可以是http:的
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke('pdf-sign_PdfView', { filePath: filePath, cookies: cookies }, callback);
      } else if (!callback && typeof cookies === 'function') {
        //缺少1个参数,我们兼容缺少cookies的情况
        callback = cookies;
        cookies = null;
        baseInvoke('pdf-sign_PdfView', { filePath: filePath }, callback);
      } else {
        throw new Error('cusPdfFileView的调用参数非法!');
      }
    },
    /**
     * PDF格式检查 Base64编码的PDF
     * @param fileContent Base64编码的PDF文件
     * @param blankBookAuthorityCheck 字体或空白页检查未通过,是否视为检查失败.
     * @param callback
     */
    cusPdfContentCheck: function(fileContent, blankBookAuthorityCheck, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvokeByFrames(
          'pdf-sign_PdfCheck',
          {
            fileContent: fileContent,
            blankBookAuthorityCheck: blankBookAuthorityCheck,
          },
          callback
        );
      } else if (!callback && typeof blankBookAuthorityCheck === 'function') {
        //缺少1个参数,我们兼容缺少blankBookAuthorityCheck的情况
        callback = blankBookAuthorityCheck;
        blankBookAuthorityCheck = null;
        baseInvokeByFrames('pdf-sign_PdfCheck', { fileContent: fileContent }, callback);
      } else {
        throw new Error('cusPdfContentCheck的调用参数非法!');
      }
    },
    /**
     * PDF格式检查 本地文件的PDF
     * @param filePath 文件全路径
     * @param cookies Http地址需要的Cookies
     * @param blankBookAuthorityCheck 字体或空白页检查未通过,是否视为检查失败.
     * @param callback
     */
    cusPdfFileCheck: function(filePath, cookies, blankBookAuthorityCheck, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-sign_PdfCheck',
          {
            filePath: filePath,
            cookies: cookies,
            blankBookAuthorityCheck: blankBookAuthorityCheck,
          },
          callback
        );
      } else if (!callback && typeof blankBookAuthorityCheck === 'function') {
        //缺少1个参数,我们兼容缺少blankBookAuthorityCheck的情况
        callback = blankBookAuthorityCheck;
        blankBookAuthorityCheck = null;
        baseInvoke(
          'pdf-sign_PdfCheck',
          {
            filePath: filePath,
            cookies: cookies,
          },
          callback
        );
      } else if (!callback && typeof cookies === 'function') {
        //缺少2个参数,我们兼容缺少blankBookAuthorityCheck和cookies的情况
        callback = cookies;
        cookies = null;
        baseInvoke(
          'pdf-sign_PdfCheck',
          {
            filePath: filePath,
          },
          callback
        );
      } else {
        throw new Error('cusPdfFileCheck的调用参数非法!');
      }
    },
    /**
     * Base64编码的PDF验签名(使用方正组件)
     * @param fileContent Base64编码的PDF文件
     * @param blankBookAuthorityCheck 字体或空白页检查未通过,是否视为检查失败.
     * @param callback
     */
    cusPdfContentCheckSign: function(fileContent, blankBookAuthorityCheck, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvokeByFrames(
          'pdf-sign_PdfCheckSign',
          {
            fileContent: fileContent,
            blankBookAuthorityCheck: blankBookAuthorityCheck,
          },
          callback
        );
      } else if (!callback && typeof blankBookAuthorityCheck === 'function') {
        //缺少1个参数,我们兼容缺少blankBookAuthorityCheck的情况
        callback = blankBookAuthorityCheck;
        blankBookAuthorityCheck = null;
        baseInvokeByFrames('pdf-sign_PdfCheckSign', { fileContent: fileContent }, callback);
      } else {
        throw new Error('cusPdfContentCheckSign的调用参数非法!');
      }
    },
    /**
     * PDF文件验签名(使用方正组件)
     * @param filePath 文件全路径
     * @param cookies Http地址需要的Cookies
     * @param blankBookAuthorityCheck 字体或空白页检查未通过,是否视为检查失败.
     * @param callback
     */
    cusPdfFileCheckSign: function(filePath, cookies, blankBookAuthorityCheck, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-sign_PdfCheckSign',
          {
            filePath: filePath,
            cookies: cookies,
            blankBookAuthorityCheck: blankBookAuthorityCheck,
          },
          callback
        );
      } else if (!callback && typeof blankBookAuthorityCheck === 'function') {
        //缺少1个参数,我们兼容缺少cookies的情况
        callback = blankBookAuthorityCheck;
        blankBookAuthorityCheck = null;
        baseInvoke('pdf-sign_PdfCheckSign', { filePath: filePath, cookies: cookies }, callback);
      } else if (!callback && typeof cookies === 'function') {
        //缺少1个参数,我们兼容缺少cookies的情况
        callback = cookies;
        cookies = null;
        baseInvoke('pdf-sign_PdfCheckSign', { filePath: filePath }, callback);
      } else {
        throw new Error('cusPdfSignCheckSign的调用参数非法!');
      }
    },
    /**
     * Base64编码的PDF内容签章
     * @param fileContent Base64编码的PDF文件
     * @param datetiem 签章时间戳
     * @param Edoc_code edoc类型编码
     * @param Edoc_Name edoc类型名称
     * @param passwd 卡密码
     * @param callback
     */
    cusPdfContentAddSign: function(fileContent, datetiem, Edoc_code, Edoc_Name, passwd, callback) {
      //destDir,fileName,
      //少1个参数,认为没传userpin,少两个,认为没传认为没传userpin和Edoc_Name,保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvokeByFrames(
          'pdf-sign_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvokeByFrames(
          'pdf-sign_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvokeByFrames(
          'pdf-sign_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
      }
    },
    /**
     * 对PDF文件签章,支持本地和Http
     * @param filePath
     * @param fileName
     * @param datetiem 签章时间戳
     * @param Edoc_code edoc类型编码
     * @param Edoc_Name edoc类型名称
     * @param cookies
     * @param passwd 卡密码
     * @param callback
     */
    cusPdfFileAddSign: function(
      filePath,
      fileName,
      datetiem,
      Edoc_code,
      Edoc_Name,
      cookies,
      passwd,
      callback
    ) {
      //destDir,fileName,
      //少1个参数,认为没传passwd;少2个,认为没传认为没传cookies和passwd;少3个,认为没传认为没传Edoc_Name/cookies和userpin.保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-sign_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            cookies: cookies,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'pdf-sign_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            cookies: cookies,
          },
          callback
        );
      } else if (!callback && typeof cookies === 'function') {
        //缺少2个参数,我们兼容缺少cookies和passwd的情况
        callback = cookies;
        cookies = null;
        baseInvoke(
          'pdf-sign_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少3个参数,我们兼容缺少Edoc_Name/cookies和passwd的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke(
          'pdf-sign_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
      }
    },
    /**
     * 对本地PDF文件签章,并覆盖之...
     * @param filePath
     * @param Edoc_code edoc类型编码
     * @param Edoc_Name edoc类型名称
     * @param datetiem 签章时间戳
     * @param passwd 卡密码
     * @param callback 回调函数
     */
    cusFilePdfAddSign: function(filePath, Edoc_code, Edoc_Name, datetiem, passwd, callback) {
      //少1个参数,认为没传passwd;少2个,认为没传认为没传datetiem和passwd.保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'pdf-sign_FilePdfAddSign',
          {
            filePath: filePath,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            datetiem: datetiem,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'pdf-sign_FilePdfAddSign',
          {
            filePath: filePath,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            datetiem: datetiem,
          },
          callback
        );
      } else if (!callback && typeof datetiem === 'function') {
        //缺少2个参数,我们兼容缺少cookies和passwd的情况
        callback = datetiem;
        datetiem = null;
        baseInvoke(
          'pdf-sign_FilePdfAddSign',
          {
            filePath: filePath,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
      }
    },
    /**
     * PDF批量检查
     * @param args
     * @param callback
     */
    cusPdfFileBatchCheck: function(args, callback) {
      baseInvoke('pdf-sign_PdfFileBatchCheck', args, callback);
    },
    /**
     * PDF文件批量加签名,加签之前不检查文件
     * @param args
     * @param callback
     */
    cusPdfFileBatchAddSign: function(args, callback) {
      //args为js对象,不是json字符串!
      baseInvoke('pdf-sign_PdfFileBatchAddSign', args, callback);
    },
    /**
     * PDF文件批量检查和加签名
     * @param args
     * @param callback
     */
    cusPdfFileBatchCheckAndSign: function(args, callback) {
      //args为js对象,不是json字符串!
      baseInvoke('pdf-sign_PdfFileBatchCheckAndSign', args, callback);
    },
    /**
     * Xml中的的PDF内容加签名,需要的信息也全部在Xml中的节点上保存.
     * @param filePath Xml文件的本地路径
     * @param FileContent_NodeName PDF内容节点路径
     * @param Edoc_code_NodeName EDoc_code的节点路径
     * @param Edoc_Name_NodeName Edoc_Name的节点路径,可以为空
     * @param datetiem 加签时间,可以为空
     * @param replace [Y/N]是否替换原文件,可为空,默认值N
     * @param suffix_rule 不替换源文件的情况下,新的文件保存的后缀的规则
     * @param outDir 输出目录
     * @param passwd 卡的密码
     * @param callback
     * @author 王立鹏
     */
    cusXmlPdfFileAddSign: function(
      filePath,
      FileContent_NodeName,
      Edoc_code_NodeName,
      Edoc_Name_NodeName,
      datetiem,
      replace,
      suffix_rule,
      outDir,
      passwd,
      callback
    ) {
      baseInvoke(
        'pdf-sign_PdfXmlAddSign',
        {
          filePath: filePath,
          FileContent_nodepath: FileContent_NodeName,
          Edoc_code_nodepath: Edoc_code_NodeName,
          Edoc_Name_nodepath: Edoc_Name_NodeName,
          datetiem: datetiem,
          replace: replace,
          suffix_rule: suffix_rule,
          outDir: outDir,
          passwd: passwd,
        },
        callback
      );
    },
    /**
     *  批量对Xml中的的PDF内容加签名,需要的信息也全部在Xml中的节点上保存.
     * @param args :{
     *   passwd:"卡密码",
     *   FileContent_nodepath:"Xml中的数据节点位置",
     *   datetiem:"加签时间,可以为空",
     *   Edoc_code_nodepath:"Edoc_code的节点位置.",
     *   Edoc_Name_nodepath:"Edoc_Name的节点位置.",
     *   rootPath:"输入文件的基础目录,可以为空",
     *   replace:"Y/N是否覆盖原文件",
     *   suffix_rule:"后缀规则,如果填写,则修改Xml后缀,放到源文件目录中.仅当replace=N的时候生效 ",
     *   outDir:"输出目录. 仅当replace=N的时候生效",
     *   filesInfo:[
     *       {filePath:"XML文件全路径1"},
     *       {filePath:"XML文件全路径2"}
     *   ]
     *}
     * @param callback
     */
    cusXmlPdfBatchFileAddSign: function(args, callback) {
      baseInvoke('pdf-sign_PdfXmlBatchAddSign', args, callback);
    },
    /**
     * 对整个目录中的全部Xml中的的PDF内容加签名,需要的信息也全部在Xml中的节点上保存.
     * @param rootPath Xml文件所在的目录
     * @param FileContent_NodeName PDF内容节点路径
     * @param Edoc_code_NodeName EDoc_code的节点路径
     * @param Edoc_Name_NodeName Edoc_Name的节点路径,可以为空
     * @param datetiem 加签时间,可以为空
     * @param replace [Y/N]是否替换原文件,可为空,默认值N
     * @param suffix_rule 不替换源文件的情况下,新的文件保存的后缀的规则
     * @param outDir 输出目录
     * @param passwd 卡的密码
     * @param callback
     * @author 王立鹏
     */
    cusXmlPdfDirAddSign: function(
      rootPath,
      FileContent_NodeName,
      Edoc_code_NodeName,
      Edoc_Name_NodeName,
      datetiem,
      replace,
      suffix_rule,
      outDir,
      passwd,
      callback
    ) {
      baseInvoke(
        'pdf-sign_PdfXmlDirAddSign',
        {
          rootPath: rootPath,
          FileContent_nodepath: FileContent_NodeName,
          Edoc_code_nodepath: Edoc_code_NodeName,
          Edoc_Name_nodepath: Edoc_Name_NodeName,
          datetiem: datetiem,
          replace: replace,
          suffix_rule: suffix_rule,
          outDir: outDir,
          passwd: passwd,
        },
        callback
      );
    },

    /*----------------------------------PDFES的签章插件-------------------------------------------------------------*/
    /**
     * 提取印章图片
     * @param callback
     */
    pdfesExtractSeal: function(callback) {
      baseInvoke('pdf-es_ExtractSeal', {}, callback);
    },
    /**
     * 设置服务器URL地址
     * @param url url内容，string类型
     * @param callback
     */
    pdfesSetServerUrl: function(url, callback) {
      baseInvoke('pdf-es_SetServerUrl', { url: url }, callback);
    },
    /**
     * 验证文档所有签章
     * @param fileData 待验签文档内容，base64编码的字符串
     * @param callback
     */
    pdfesVerifySeal: function(sessionId, fileData, callback) {
      baseInvokeByFrames(
        'pdf-es_VerifySeal',
        { sessionId: sessionId, fileData: fileData },
        callback
      );
    },
    /**
     * 电子签章
     * @param orignFile 待签章文件内容数据，base64编码的字符串
     * @param seSeal 印章数据内容，base64编码的字符串
     * @param cert 签章人证书，base64编码的字符串
     * @param left 签章距文件左边界距离，数值类型
     * @param top 签章距文件上边界距离，数值类型
     * @param callback
     */
    pdfesSign: function(sessionId, orignFile, seSeal, cert, left, top, callback) {
      baseInvokeByFrames(
        'pdf-es_Sign',
        {
          sessionId: sessionId,
          orignFile: orignFile,
          seSeal: seSeal,
          cert: cert,
          left: left,
          top: top,
        },
        callback
      );
    },

    /*----------------------------------商务部安全功能---------------------------------------------------------------*/
    /**
     * 判断是否插入了UKey
     * @param callback
     */
    mofcomDetectKey: function(callback) {
      baseInvoke('mofcom_DetectKey', {}, callback);
    },
    /**
     * 获取Usb-Key的序列号(ID)
     */
    mofcomGetFTKeySN: function(callback) {
      baseInvoke('mofcom_GetFTKeySN', {}, callback);
    },
    /**
     * 获取选用的证书下标
     * @param callback
     */
    mofcomGetSelectedCertIndex: function(callback) {
      baseInvoke('mofcom_GetSelectedCertIndex', {}, callback);
    },
    /**
     * 证书列表
     * @param callback
     */
    mofcomListCertsNames: function(callback) {
      baseInvoke('mofcom_ListCertsNames', {}, callback);
    },
    /**
     * 设置选用证书
     * @param index
     * @param callback
     */
    mofcomSetSelectedCertIndex: function(index, callback) {
      baseInvoke('mofcom_SetSelectedCertIndex', { index: index }, callback);
    },
    /**
     * 验证证书密码
     * @param passwd
     * @param callback
     */
    mofcomCheckUsbKeyPin: function(passwd, callback) {
      baseInvoke('mofcom_CheckUsbKeyPin', { passwd: passwd }, callback);
    },
    /**
     * 获取证书
     * @param callback
     */
    mofcomGetEncodedCert: function(callback) {
      baseInvoke('mofcom_GetEncodedCert', {}, callback);
    },
    /**
     * 获取证书信息
     * @param callback
     */
    mofcomGetCertInfo: function(callback) {
      baseInvoke('mofcom_GetCertInfo', {}, callback);
    },
    /**
     * 对信息加签
     * @param message 待签名的内容
     * @param callback
     */
    mofcomSignMessage: function(message, callback) {
      baseInvoke('mofcom_SignMessage', { message: message }, callback);
    },
    /**
     * 信息批量签名
     * @param messages
     * @param callback
     */
    mofcomBatchSignMessage: function(messages, callback) {
      baseInvokeByFrames('mofcom_BatchSignMessage', { messages: messages || [] }, callback);
    },
    /**
     * 验证签名
     * @param p7message P7签名数据
     * @param message 原始数据
     * @param callback
     */
    mofcomVerifyMsg: function(p7message, message, callback) {
      baseInvoke('mofcom_VerifyMsg', { p7message: p7message, message: message }, callback);
    },
    /**
     * 批量验证签名
     * @param p7messages P7签名数据数组
     * @param messages 原始数据数组
     * @param callback
     */
    mofcomBatchVerifyMsg: function(p7messages, messages, callback) {
      baseInvokeByFrames(
        'mofcom_BatchVerifyMsg',
        {
          p7messages: p7messages || [],
          messages: messages || [],
        },
        callback
      );
    },
    /**
     * 签名本地文件
     * @param inFile 文件全路径
     * @param callback
     */
    mofcomEnvelopedSignFile: function(inFile, callback) {
      baseInvoke('mofcom_EnvelopedSignFile', { inFile: inFile }, callback);
    },
    /**
     * 验签本地文件
     * @param p7message P7签名信息
     * @param inFile 本地文件
     * @param callback
     */
    mofcomEnvelopedVerifyFile: function(p7message, inFile, callback) {
      baseInvoke('mofcom_EnvelopedVerifyFile', { p7message: p7message, inFile: inFile }, callback);
    },

    /*----------------------------------旧版过时的功能功能------------------------------------------------------------*/
    /**
     * 启动微软ClickOnes程序
     * @param qpurl
     * @param casurl
     * @param passwd
     * @param callback
     * @deprecated
     */
    startClickOnceApp: function(qpurl, casurl, passwd, callback) {
      baseInvoke(
        'base_StartClickOnceApp',
        { qpurl: qpurl, casurl: casurl, passwd: passwd },
        callback
      );
    },
    //设置加密设备的优先级
    spcSetInitEnvPriority: function(szInitEnvPriority, callback) {
      baseInvoke(
        'security_SpcSetInitEnvPriority',
        { szInitEnvPriority: szInitEnvPriority },
        callback
      );
    },
    //打开卡
    spcInitEnvEx: function(callback) {
      baseInvoke('security_SpcInitEnvEx', callback);
    },
    //关闭卡
    spcClearEnv: function(callback) {
      baseInvoke('security_SpcClearEnv', callback);
    },
    //下面是客户端控件组件的调用接口
    login: function(passwd, callback) {
      baseInvoke('security_login', { passwd: passwd }, callback);
    },
    signData: function(passwd, inputData, callback) {
      baseInvoke('security_signData', { passwd: passwd, inputData: inputData }, callback);
    },
    spcSignData: function(inData, callback) {
      baseInvoke('security_SpcSignData', { inData: inData }, callback);
    },
    spcSignDataAsPEM: function(inData, callback) {
      baseInvoke('security_SpcSignDataAsPEM', { inData: inData }, callback);
    },
    spcSignPemDataAsPEM: function(inData, callback) {
      baseInvoke('security_SpcSignPemDataAsPem', { inData: inData }, callback);
    },
    spcSignDataNoHash: function(inData, callback) {
      baseInvoke('security_SpcSignDataNoHash', { inData: inData }, callback);
    },
    spcSignDataNoHashAsPEM: function(inData, callback) {
      baseInvoke('security_SpcSignDataNoHashAsPEM', { inData: inData }, callback);
    },
    spcVerifySignData: function(certDataPEM, inData, signData, callback) {
      baseInvoke(
        'security_SpcVerifySignData',
        {
          certDataPEM: certDataPEM,
          inData: inData,
          signData: signData,
        },
        callback
      );
    },
    spcVerifySignDataNoHash: function(certDataPEM, inData, signData, callback) {
      baseInvoke(
        'security_SpcVerifySignDataNoHash',
        {
          certDataPEM: certDataPEM,
          inData: inData,
          signData: signData,
        },
        callback
      );
    },
    spcSHA1Digest: function(szInfo, callback) {
      baseInvoke('security_SpcSHA1Digest', { szInfo: szInfo }, callback);
    },
    spcSHA1DigestAsPEM: function(szInfo, callback) {
      baseInvoke('security_SpcSHA1DigestAsPEM', { szInfo: szInfo }, callback);
    },

    spcGetCardID: function(callback) {
      baseInvoke('security_SpcGetCardID', callback);
    },
    spcGetCertNo: function(callback) {
      baseInvoke('security_SpcGetCertNo', callback);
    },
    spcGetUName: function(callback) {
      baseInvoke('security_SpcGetUName', callback);
    },
    spcGetEntID: function(callback) {
      baseInvoke('security_SpcGetEntID', callback);
    },
    spcGetEntName: function(callback) {
      baseInvoke('security_SpcGetEntName', callback);
    },
    spcGetEntMode: function(callback) {
      baseInvoke('security_SpcGetEntMode', callback);
    },
    spcGetCardUserInfo: function(callback) {
      baseInvoke('security_SpcGetCardUserInfo', callback);
    },
    getGetCardUserInfoAll: function(userpin, callback) {
      //新增 by wlp 2017年11月15日,2017年11月29日 增加userpin
      if (!callback && typeof userpin === 'function') {
        callback = userpin;
        userpin = null;
        baseInvoke('security_getGetCardUserInfoAll', {}, callback);
      } else {
        baseInvoke('security_getGetCardUserInfoAll', { userpin: userpin }, callback);
      }
    },
    spcGetCardAttachInfo: function(callback) {
      baseInvoke('security_SpcGetCardAttachInfo', callback);
    },
    spcGetCardAttachInfoAsPEM: function(callback) {
      baseInvoke('security_SpcGetCardAttachInfoAsPEM', callback);
    },
    spcVerifyPIN: function(passwd, callback) {
      baseInvoke('security_SpcVerifyPIN', { passwd: passwd }, callback);
    },
    spcChangePIN: function(oldPin, newPin, callback) {
      baseInvoke('security_SpcChangePIN', { oldPin: oldPin, newPin: newPin }, callback);
    },
    spcEncodePEM: function(inData, callback) {
      baseInvoke('security_SpcEncodePEM', { inData: inData }, callback);
    },
    spcDecodePEM: function(inData, callback) {
      baseInvoke('security_SpcDecodePEM', { inData: inData }, callback);
    },
    spcDecodePEMAsString: function(inData, callback) {
      baseInvoke('security_SpcDecodePEMAsString', { inData: inData }, callback);
    },
    spcGetSignCert: function(callback) {
      baseInvoke('security_SpcGetSignCert', callback);
    },
    spcGetSignCertAsPEM: function(callback) {
      baseInvoke('security_SpcGetSignCertAsPEM', callback);
    },
    spcGetEnvCert: function(callback) {
      baseInvoke('security_SpcGetEnvCert', callback);
    },
    spcGetEnvCertAsPEM: function(callback) {
      baseInvoke('security_SpcGetEnvCertAsPEM', callback);
    },
    spcGetValidTimeFromCert: function(certByteArray, callback) {
      if (typeof certByteArray === 'function') {
        callback = certByteArray;
        certByteArray = null;
      }
      baseInvoke(
        'security_SpcGetValidTimeFromCert',
        !!certByteArray ? { certByteArray: certByteArray } : {},
        callback
      );
    },
    spcGetValidTimeAll: function(callback) {
      //2017年11月01日 增加 by 王立鹏
      baseInvoke('security_getValidTimeAll', {}, callback);
    },
    spcSignRandom: function(passwd, random, callback) {
      baseInvoke('security_SpcSignRandom', { passwd: passwd, random: random }, callback);
    },
    spcRSAEncrypt: function(inData, certData, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_SpcRSAEncrypt',
          {
            inData: inData,
            certData: certData,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'security_SpcRSAEncrypt',
          {
            inData: inData,
            certData: certData,
          },
          callback
        );
      } else {
        throw new Error('spcRSAEncrypt的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    spcRSADecrypt: function(inData, passwd, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_SpcRSADecrypt',
          {
            inData: inData,
            passwd: passwd,
          },
          callback
        );
      } else if (!callback && typeof passwd === 'function') {
        //缺少1个参数,我们兼容缺少passwd的情况
        callback = passwd;
        passwd = null;
        baseInvoke(
          'security_SpcRSADecrypt',
          {
            inData: inData,
          },
          callback
        );
      } else {
        throw new Error('spcRSAEncrypt的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    pdfSignCheckSign: function(fileContent, callback) {
      baseInvokeByFrames('security_PdfSignCheckSign', { fileContent: fileContent }, callback);
    },
    localPdfSignCheckSign: function(filePath, callback) {
      baseInvoke('security_PdfSignCheckSign', { filePath: filePath }, callback);
    },
    pdfSignCheck: function(fileContent, callback) {
      baseInvokeByFrames('security_PdfSignCheck', { fileContent: fileContent }, callback);
    },
    localPdfSignCheck: function(filePath, callback) {
      baseInvoke('security_PdfSignCheck', { filePath: filePath }, callback);
    },
    pdfAddSign: function(fileContent, datetiem, Edoc_code, Edoc_Name, userpin, callback) {
      //destDir,fileName,
      //少1个参数,认为没传userpin,少两个,认为没传认为没传userpin和Edoc_Name,保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvokeByFrames(
          'security_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            userpin: userpin,
          },
          callback
        );
      } else if (!callback && typeof userpin === 'function') {
        //缺少1个参数,我们兼容缺少userpin的情况
        callback = userpin;
        userpin = null;
        baseInvokeByFrames(
          'security_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少1个参数,我们兼容缺少userpin的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvokeByFrames(
          'security_PdfAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    localPdfAddSign: function(
      filePath,
      fileName,
      datetiem,
      Edoc_code,
      Edoc_Name,
      cookies,
      userpin,
      callback
    ) {
      //destDir,fileName,
      //少1个参数,认为没传userpin;少2个,认为没传认为没传cookies和userpin;少3个,认为没传认为没传Edoc_Name/cookies和userpin.保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            cookies: cookies,
            userpin: userpin,
          },
          callback
        );
      } else if (!callback && typeof userpin === 'function') {
        //缺少1个参数,我们兼容缺少userpin的情况
        callback = userpin;
        userpin = null;
        baseInvoke(
          'security_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            cookies: cookies,
          },
          callback
        );
      } else if (!callback && typeof cookies === 'function') {
        //缺少2个参数,我们兼容缺少cookies和userpin的情况
        callback = cookies;
        cookies = null;
        baseInvoke(
          'security_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少3个参数,我们兼容缺少Edoc_Name/cookies和userpin的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke(
          'security_PdfAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    pdfCheckAndAddSign: function(fileContent, datetiem, Edoc_code, Edoc_Name, callback) {
      //destDir,fileName,
      //少1个参数,认为没传destDir,少两个,认为没传认为没传destDir和Edoc_Name,保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvokeByFrames(
          'security_PdfCheckAndAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少1个参数,我们兼容缺少Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvokeByFrames(
          'security_PdfCheckAndAddSign',
          {
            fileContent: fileContent,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    localPdfCheckAndAddSign: function(
      filePath,
      fileName,
      datetiem,
      Edoc_code,
      Edoc_Name,
      cookies,
      callback
    ) {
      //destDir,fileName,
      //少1个参数,认为没传cookies,少两个,认为没传认为没传cookies和Edoc_Name,保证callback必须得有!
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_PdfCheckAndAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            cookies: cookies,
          },
          callback
        );
      } else if (!callback && typeof cookies === 'function') {
        //缺少1个参数,我们兼容缺少Edoc_Name的情况
        callback = cookies;
        cookies = null;
        baseInvoke(
          'security_PdfCheckAndAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少2个参数,我们兼容缺少cookies和Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke(
          'security_PdfCheckAndAddSign',
          {
            filePath: filePath,
            fileName: fileName,
            datetiem: datetiem,
            Edoc_code: Edoc_code,
          },
          callback
        );
      } else {
        throw new Error('addSign的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    pdfScanInit: function(callback) {
      baseInvoke('security_PdfScanScanInitialize', {}, callback);
    },
    pdfScanAsPEM: function(Edoc_code, Edoc_Name, userpin, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_PdfScanAsPEM',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            userpin: userpin,
          },
          callback
        );
      } else if (!callback && typeof userpin === 'function') {
        //缺少1个参数,我们兼容缺少userpin的情况
        callback = userpin;
        userpin = null;
        baseInvoke(
          'security_PdfScanAsPEM',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少2个参数,我们兼容缺少userpin和Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke('security_PdfScanAsPEM', { Edoc_code: Edoc_code }, callback);
      }
    },
    pdfScan: function(Edoc_code, Edoc_Name, userpin, callback) {
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke(
          'security_PdfScan',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
            userpin: userpin,
          },
          callback
        );
      } else if (!callback && typeof userpin === 'function') {
        //缺少1个参数,我们兼容缺少userpin的情况
        callback = userpin;
        userpin = null;
        baseInvoke(
          'security_PdfScan',
          {
            Edoc_code: Edoc_code,
            Edoc_Name: Edoc_Name,
          },
          callback
        );
      } else if (!callback && typeof Edoc_Name === 'function') {
        //缺少2个参数,我们兼容缺少userpin和Edoc_Name的情况
        callback = Edoc_Name;
        Edoc_Name = null;
        baseInvoke('security_PdfScan', { Edoc_code: Edoc_code }, callback);
      }
    },
    pdfView: function(fileContent, callback) {
      //destDir,fileName,
      baseInvokeByFrames('security_PdfView', { fileContent: fileContent }, callback);
    },
    localPdfView: function(filePath, cookies, callback) {
      //filePath可以是本地的file:,也可以是http:的
      if (callback && typeof callback === 'function') {
        //完整参数
        baseInvoke('security_PdfView', { filePath: filePath, cookies: cookies }, callback);
      } else if (!callback && typeof cookies === 'function') {
        //缺少1个参数,我们兼容缺少title的情况
        callback = cookies;
        cookies = null;
        baseInvoke('security_PdfView', { filePath: filePath }, callback);
      } else {
        throw new Error('addSign的调用参数非法!');
        //alert("addSign的调用参数非法");
      }
    },
    localPdfBatchCheckAndSign: function(args, callback) {
      //args为js对象,不是json字符串!
      baseInvoke('security_LocalPdfBatchCheckAndSign', args, callback);
    },
    localPdfBatchUpload: function(args, callback) {
      baseInvoke('security_LocalPdfBatchUpload', args, callback);
    },
    deleteSignedTempFile: function(args, callback) {
      baseInvoke('security_DeleteSignedTempFile', args, callback);
    },

    //下面是单一窗口组件的调用接口
    swcLogin: function(passwd, callback) {
      baseInvoke('swc_security_login', { passwd: passwd }, callback);
    },
    swcPostData: function(data, callback, method) {
      conn();
      method = method || 'swc_postdata';
      callbacks[method] = callback;
      var _data = { _method: method };
      _data['_id'] = id++;
      if (typeof data === 'object') {
        _data['args'] = toJson(data);
      } else {
        _data['args'] = data;
      }
      var s = toJson(_data);
      //2016年10月27日 分块改为顺序传输
      //校验码
      var checkCode = DIGEST.CheckCode(s);
      //分包的组
      var guid = getGuid();
      while (blockData[guid]) {
        //存在则重新生成一个!
        guid = getGuid();
      }
      //数据分块
      var splitData = splitStrData(s);
      //如果需要分包传输
      if (splitData.length > 1) {
        blockData[guid] = {
          checkcode: checkCode,
          totalLength: s.length,
          retry: 0,
          block: splitData,
        };
      }
      //传第一个包
      //报头(纯文本类型)含义
      //"BLOCKTXT"+总校验码(4字节)+块校验码(4字节)+数据总大小(16字节)+当前块大小(8字节)+是否分块/分为几块(4字节)+数据分块组号(36字节)+数据包号(4字节)+保留位(44字节),总计128字长
      //        8               12              16                 32                40                       44                   80              84            128
      var blockCheckCode = DIGEST.CheckCode(splitData[0]);
      var pakHeaser = getDataHeader(
        checkCode,
        blockCheckCode,
        s.length,
        splitData[0].length,
        splitData.length,
        guid,
        0
      );
      var msg = pakHeaser + splitData[0];
      sendMessage(msg);
    },
    data: function() {},
  };
  //单一窗口组件兼容调用..
  EportClient.data.prototype = {
    Execute: function(callback) {
      var d = toJson(this);
      EportClient.swcPostData(d, callback);
    },
  };
})(window, document, navigator);
//client.js end ------------

/**
 * 用户是否已经点击登陆按钮
 */
var isLoginButtonPressed;

/**
 * 密码节点
 */
// export const upnode = document.getElementById('password');

/**
 * 显示提示信息的节点
 */
export let infonode;

/**
 * 初始化函数，做一些页面初始信息的获取
 */
export function init(i) {
  var steupinfo = document.getElementById('setupinfo');
  if (steupinfo != undefined) {
    document.body.removeChild(steupinfo);
  }
  isLoginButtonPressed = false;
  syncStatus(); //同步状态信息
  if (!isInstalled()) {
    return;
  }
  const upnode = document.getElementById('password');
  try {
    upnode.focus();
  } catch (e) {}
}

/**
 * 封装获取元素节点的value属性值
 * 输入参数可以是1-n个节点的id属性值
 * 返回值是一个元素节点或一个包含所有元素节点的value值的数组
 */
export function $V() {
  var values = new Array();
  for (var i = 0; i < arguments.length; i++) {
    var value = arguments[i];
    if (typeof value == 'string') {
      var tempnode = document.getElementById(value);
      if (tempnode == null || !tempnode.value) {
        value = null;
      } else {
        value = document.getElementById(value).value;
      }
    }
    if (arguments.length == 1) {
      return value;
    }
    values.push(value);
  }
  return values;
}

/**
 * 新建一个文本节点
 * @param content 文本节点内容
 * @return 文本节点
 */
export function $CT(content) {
  return document.createTextNode(content);
}

/**
 * 封装获取元素节点中包含的唯一文本节点内容的方法
 * 输入参数可以是1-n个节点的id属性值
 * 返回值是一个元素节点或一个包含所有元素节点内部的唯一为本节点内容的数据
 */
export function $T() {
  var texts = new Array();
  for (var i = 0; i < arguments.length; i++) {
    var text = arguments[i];
    if (typeof text == 'string') {
      var temp = document.getElementById(text);
      if (temp == null) {
        text = null;
      } else {
        var tempnode = document.getElementById(text).firstChild;
        if (tempnode == null) {
          text = null;
        } else {
          text = tempnode.nodeValue;
        }
      }
    }
    if (arguments.length == 1) {
      return text;
    }
    texts.push(text);
  }
  return texts;
}

/**
 * 键盘按下时处理事件
 */
export function keyp(event) {
  const upnode = document.getElementById('password');
  var ev;
  if (event) {
    ev = event;
  } else {
    ev = window.event;
  }
  if (ev.keyCode == 13) {
    doCAIdentify();
  }
}

/**
 * 用户提交登陆认证请求入口
 */
export function doCAIdentify({ callback }) {
  // if (isLoginButtonPressed == true) {
  //   return;
  // }
  // isLoginButtonPressed = true;
  infonode = document.getElementById('info');
  if (infonode != null) {
    infonode.style.display = 'none';
    infonode.style.backgroundColor = '';
    infonode.innerHTML = '';
  }
  showinfo();
  let userpassword = $V('password');
  if (userpassword == null || userpassword.length < 1) {
    clearinfo();
    alert('IC卡/Key密码不允许为空');
    const upnode = document.getElementById('password');
    upnode.value = '';
    upnode.focus();
    isLoginButtonPressed = false;
    return;
  }
  checkPwd(userpassword).then(data => {
    callback(data);
  });
  //		setStatus("开始进行密码验证...");
}

/**
 * 清除登录提示信息
 */
export function clearinfo() {
  if (infonode != null) {
    infonode.style.display = 'none';
    infonode.style.backgroundColor = '';
    infonode.innerHTML = '';
  }
}

//校验密码 并返回卡信息
export function checkPwd(strPwd) {
  var cPw = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8'); //密码组
  var Max = 8;
  if (strPwd == '') {
    alert('您输入的IC卡/Key密码不能为空');
    isLoginButtonPressed = false;
    return -1;
  }
  for (let i = 0; i <= Max; i++) {
    if (strPwd == cPw[i]) {
      alert('请正确输入8位IC卡/Key密码');
      clearinfo();
      const upnode = document.getElementById('password');
      upnode.value = '';
      upnode.focus();
      isLoginButtonPressed = false;
      return -2;
    }
  }

  return new Promise(resolve => {
    EportClient.isInstalledTest(
      EportClient.spcSignRandom,
      strPwd,
      document.getElementById('random').value,
      function(msg) {
        resolve(msg);
        HandleSignResult(msg);
      }
    );
  });
}

//检查是否插卡了，使用取签名证书来验证
export function HandleCheckInsCardResult(msg) {
  if (msg.Result) {
    EportClient.spcGetSignCert(HandleCheckInsCardStausResult);
  } else {
    if (
      JSON.stringify(msg.Error).indexOf('51590') > 0 ||
      JSON.stringify(msg.Error).indexOf('50200') > 0
    ) {
      alert('请插入IC卡或者Key!');
    } else {
      alert(msg.Error);
    }

    isLoginButtonPressed = false;
    EportClient.spcClearEnv();
  }
}

//检查是否插卡了，结果处理
export function HandleCheckInsCardStausResult(msg) {
  if (msg.Result) {
    HandleVerifyPINResult(msg);
  } else {
    if (msg.Error && msg.Error != '') {
      if (
        JSON.stringify(msg.Error).indexOf('51590') > 0 ||
        JSON.stringify(msg.Error).indexOf('50200') > 0
      ) {
        alert('请插入IC卡或者Key');
      } else {
        alert(msg.Error);
      }
      clearinfo();
      isLoginButtonPressed = false;
      EportClient.spcClearEnv();
    }
  }
}

//检查Pin密码
export function HandleVerifyPINResult(msg) {
  var strPwd = $V('password');
  EportClient.spcVerifyPIN(strPwd, HandleCheckPwdResult);
}

//处理验证密码结果
export function HandleCheckPwdResult(msg) {
  if (msg.Result) {
    EportClient.spcSignPemDataAsPEM($V('random'), HandleSignResult);
  } else {
    if (msg.Error && msg.Error != '') {
      alert(msg.Error);
      clearinfo();
      const upnode = document.getElementById('password');
      upnode.value = '';
      upnode.focus();
      isLoginButtonPressed = false;
      return;
    } else {
      window.opener = null;
      window.open('', '_self', '');
      window.close();
    }
  }
}

//处理签名结果
export function HandleSignResult(msg) {
  if (msg.Result) {
    //$("signData").value=(msg.Data)[0];
    document.getElementById('signData').value = msg.Data[0];
    //EportClient.spcGetCardUserInfo(HandleCardUerInfoResult);
    EportClient.getGetCardUserInfoAll($V('password'), HandleCardUerInfoResult);
  } else {
    if (msg.Error && msg.Error != '') {
      alert(msg.Error);
      clearinfo();
      isLoginButtonPressed = false;
      const upnode = document.getElementById('password');
      upnode.value = '';
      upnode.focus();
      return;
    } else {
      window.opener = null;
      window.open('', '_self', '');
      window.close();
    }
  }
}
//处理用户信息
export function HandleCardUerInfoResult(msg) {
  if (msg.Result) {
    //密码验证通过后，查看证书是否过期
    getValidTimeFromCert(msg);
  } else {
    if (msg.Error && msg.Error != '') {
      alert(msg.Error);
      clearinfo();
      const upnode = document.getElementById('password');
      upnode.value = '';
      upnode.focus();
      isLoginButtonPressed = false;
      return;
    } else {
      window.opener = null;
      window.open('', '_self', '');
      window.close();
    }
  }
}

/**
 * 显示登录提示信息
 */
export function showinfo() {
  //infonode = $("info");
  infonode = document.getElementById('info');
  if (infonode != null) {
    try {
      infonode.style.display = 'block';
      infonode.style.backgroundColor = 'yellow';
      var text = $CT('登录中，请稍等');
      infonode.appendChild(text);
    } catch (ex) {
      //alert(ex);
    }
  }
}

/**
 * 检查是否安装控件
 */
export function isInstalled() {
  let res = false;
  EportClient.isInstalled(
    'iKey',
    function(msg) {
      if (msg.Result) {
        //已经安装完成了控件
        // document.getElementById('download_widget').style.display = 'none';
        res = true;
      } else {
        if (msg.Error && msg.Error != '') {
          document.getElementById('password').value = '';
          document.getElementById('password').disabled = 'true';
          isLoginButtonPressed = false;
          if ('undefined' == typeof delayAlertSetupControl) {
            if (confirm('请下载安装IC卡/Key客户端控件，否则，将无法使用IC卡/Key')) {
              downEportIkeySetup();
            }
          } else {
            delayAlertSetupControl();
          }
        } else {
          window.opener = null;
          window.open('', '_self', '');
          window.close();
        }
        res = false;
      }
    },
    'http://iKey下载地址'
  );
  return res;
}

/**
 * 单向认证标志
 */
var UNILATERAL_TYPE = '1';

/**
 * 同步状态信息：将$("status")展现到 $("info")里
 */
export function syncStatus() {
  var errmsg = document.getElementById('status');
  if (errmsg != null) {
    infonode = document.getElementById('info');
    infonode.style.display = 'block';
    var errmsgValue = $T('status');
    if (errmsgValue.split('|')[0] == '5') {
      errmsgValue = '您的证书需要延期!';
    }
    var text = $CT(errmsgValue);
    infonode.appendChild(text);
    infonode.style.display = 'block';
    infonode.style.backgroundColor = 'yellow';
  }
}

/**
 * 下载控件
 */
export function downEportIkeySetup() {
  console.log('SwVersion.getIkeyDownloadUrl()', SwVersion.getIkeyDownloadUrl());
  window.open(SwVersion.getIkeyDownloadUrl(), '_blank');
}
//开始登录
export function startLogin(msg) {
  debugger;
  var ary = new Array();
  var user = msg.Data[0];
  ary = user.split('||');
  // console.log('user', user);
  // console.log('ary', ary);
  //$("icCard").value=ary[5];
  //$("certNo").value=ary[0];
  //$("userPin").value=userpassword;
  //$("fm1").submit();

  document.getElementById('icCard').value = ary[5];
  document.getElementById('certNo').value = ary[0];
  document.getElementById('userPin').value = userpassword;
  document.getElementById('fm1').submit();

  //EportClient.spcClearEnv();
}

var errorTipDate = 30;
var symbol1 = '/';
var symbol2 = ':';
var symbol3 = ' ';

/**
 * 查看证书有效期
 *
 */
export function getValidTimeFromCert(param) {
  EportClient.isInstalledTest(EportClient.cusSpcGetValidTimeFromCert, function(msg, msgJson) {
    if (msg && !msg.Result) {
      clearinfo();
      return;
    }
    var szEndTime = msg.Data[0].szEndTime; //20190120195948

    var endTime = changeDateForm(szEndTime); //"2019/01/20 10:15:00";
    if (!endTime) {
      clearinfo();
      return;
    }

    var overDueDate = getOverDueDate(endTime);
    if (overDueDate > 0 && overDueDate <= errorTipDate) {
      alert('您的IC卡还有' + overDueDate + '天到期，请尽快延期!');
      startLogin(param);
      return;
    }
    if (overDueDate <= 0) {
      alert('您的IC卡已过期!');
      clearinfo();
      return;
    }
    startLogin(param);
  });
}
/**
 * 改变日期格式
 *"2019/01/20 10:15:00";
 */
export function changeDateForm(endTime) {
  //20190114195948
  if (endTime.length != 14) {
    return '';
  }
  var year = endTime.substring(0, 4);
  var month = endTime.substring(4, 6);
  var date = endTime.substring(6, 8);
  var hour = endTime.substring(8, 10);
  var minute = endTime.substring(10, 12);
  var second = endTime.substring(12, 14);

  return (
    year + symbol1 + month + symbol1 + date + symbol3 + hour + symbol2 + minute + symbol2 + second
  );
}
/**
 * 获取过期 天数
 */
export function getOverDueDate(endTime) {
  //"2018-01-20 10:15:00"
  //结束时间
  // 2019/01/20 10:15:00
  endStr = endTime.replace(/-/g, '/'); //一般得到的时间的格式都是：yyyy-MM-dd hh24:mi:ss，所以我就用了这个做例子，是/的格式，就不用replace了。
  var endDate = new Date(endStr); //将字符串转化为时间
  //开始时间
  var staDate = new Date();
  var num = (endDate - staDate) / (1000 * 3600 * 24); //求出两个时间的时间差，这个是天数
  var days = parseInt(Math.ceil(num)); //转化为整天（小于零的话就不用转了）
  return days;
}
